# Maintainer: Alexey Pavlov <alexpux@gmail.com>
# Contributor: Zion Nimchuk <zionnimchuk@gmail.com>
# Contributor: Mateusz Mikuła <mati865@gmail.com
# Contributor: Philippe Renon <philippe_renon@yahoo.fr>

_realname=rust
_bootstrapping=yes
if [[ $MINGW_PACKAGE_PREFIX == *-clang-aarch64 ]]; then
  _bootstrapping=no
fi
pkgbase=mingw-w64-${_realname}
pkgname=("${MINGW_PACKAGE_PREFIX}-${_realname}"
         "${MINGW_PACKAGE_PREFIX}-rust-docs")
pkgver=1.66.1
pkgrel=1
pkgdesc="Systems programming language focused on safety, speed and concurrency (mingw-w64)"
arch=('any')
mingw_arch=('mingw32' 'mingw64' 'ucrt64' 'clang64' 'clangarm64' 'clang32')
url="https://www.rust-lang.org/"
license=('MIT' 'Apache')
makedepends=("${MINGW_PACKAGE_PREFIX}-cmake"
             "${MINGW_PACKAGE_PREFIX}-curl"
             "${MINGW_PACKAGE_PREFIX}-libffi"
             "${MINGW_PACKAGE_PREFIX}-libssh2"
             "${MINGW_PACKAGE_PREFIX}-lldb"
             "${MINGW_PACKAGE_PREFIX}-llvm"
             "${MINGW_PACKAGE_PREFIX}-ninja"
             "${MINGW_PACKAGE_PREFIX}-openssl"
             "${MINGW_PACKAGE_PREFIX}-python"
             "${MINGW_PACKAGE_PREFIX}-autotools"
             $([[ "$_bootstrapping" == "no" ]] && echo "${MINGW_PACKAGE_PREFIX}-rust")
             "${MINGW_PACKAGE_PREFIX}-zlib")
options=('staticlibs' 'strip')
#install=rust.install
noextract=(${_realname}c-${pkgver}-src.tar.gz)
source=("https://static.rust-lang.org/dist/${_realname}c-${pkgver}-src.tar.gz"{,.asc}
        "0001-rustc-llvm-fix-libs.patch"
        "0004-unbundle-gcc.patch"
        "0005-win32-config.patch"
        "0007-clang-subsystem.patch"
        "0008-disable-self-contained.patch"
        "0009-build-gnullvm-targets-natively.patch"
        "0010-gnullvm-debuginfo-fix.patch"
        "0011-disable-uac-for-installer.patch"
        "0012-disable-miri.patch")
sha256sums=('5b3c933a94c72187705d4ee293198babfdd09442f5937fbd685db3a81f4959ba'
            'SKIP'
            '7cb1773c288ffb1c1e751edc49b1890c84bf9c362742bc5225d19d474edb73a0'
            '36c531c73a2c12b3e66aa22526a404c3f770f1ab7e0e76c55af6fcc1a17e46fe'
            'c4e5ffeef84296d39c3e3e8f807fc8b33ce786b1e4edb21eef26b053586aca27'
            '0784c4cb3d205ff233e61c89ce2a298b7ad2f68234b13854612d83e085fed569'
            'a214cd8394ab7416fd170c7fa05daf701a5357d38e4e54149370e6efff208e50'
            '394424aca9553802db667c3fd5cb60a5fb814ac66c5617426a5e78d1ba10d8bf'
            '84d72369303f377127a5614505c2662b530415246833569030c2578368ee070f'
            'e72ee077cd62bfc24c592a12ca27242d24ee14237d414c7e8fc4004bf8b031b8'
            'd63aaef586b08aa645ecf94165baf3c40aa7fdd3f266a5728fcf06c2a9d37f73')
validpgpkeys=('108F66205EAEB0AAA8DD5E1C85AB96E6FA1BE5FE'  # Rust Language (Tag and Release Signing Key) <rust-key@rust-lang.org>
              '474E22316ABF4785A88C6E8EA2C794A986419D8A'  # Tom Stellard <tstellar@redhat.com>
              'B6C8F98282B944E3B0D5C2530FC3042E345AD05D') # Hans Wennborg <hans@chromium.org>

# hack the bootstrap
_stage0date="2022-08-11"
_stage0version="1.63.0"
if [[ $_bootstrapping != "no" && $MINGW_PACKAGE_PREFIX == *-clang-aarch64 ]]; then
  source+=("https://github.com/mati865/rust-gnullvm-builds/releases/download/${_stage0version}-v2/cargo-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz"
           "https://github.com/mati865/rust-gnullvm-builds/releases/download/${_stage0version}-v2/rust-std-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz"
           "https://github.com/mati865/rust-gnullvm-builds/releases/download/${_stage0version}-v2/rustc-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz")
  sha256sums+=('5a72ff6d89277c96f72cb7de7f35c4a3b4686b3dc6ea0d4966883e83179db0a8'
               '0a5087acf06faa2a02ff7f41afb7be42b22575a2ff0b3f790b6bb64418f3ea5d'
               '96c7877b4821fe7bb4aaa35aa8f2056d19d622902d6583d0aef8a35f3fef8dbb')
  noextract+=("cargo-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz"
              "rust-std-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz"
              "rustc-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz")
fi

# =========================================== #
#   Helper macros to help make tasks easier   #
apply_patch_with_msg() {
  for _patch in "$@"
  do
    msg2 "Applying ${_patch}"
    patch -Nbp1 -i "${srcdir}/${_patch}"
  done
}
# =========================================== #

prepare() {
  [[ -d ${srcdir}/${_realname}c-${pkgver}-src ]] && rm -rf ${srcdir}/${_realname}c-${pkgver}-src
  tar -xzf ${srcdir}/${_realname}c-${pkgver}-src.tar.gz -C ${srcdir} || true

  cd ${srcdir}/${_realname}c-${pkgver}-src
  apply_patch_with_msg \
    0001-rustc-llvm-fix-libs.patch \
    0004-unbundle-gcc.patch \
    0005-win32-config.patch \
    0008-disable-self-contained.patch \
    0010-gnullvm-debuginfo-fix.patch \
    0012-disable-miri.patch

  if [[ $MINGW_PACKAGE_PREFIX == *-clang-i686 || $MINGW_PACKAGE_PREFIX == *-clang-x86_64 ]]; then
    apply_patch_with_msg \
      0007-clang-subsystem.patch
  fi
  if [[ $MINGW_PACKAGE_PREFIX == *-clang-aarch64 ]]; then
    apply_patch_with_msg \
      0009-build-gnullvm-targets-natively.patch
  fi
  if [[ $MINGW_PACKAGE_PREFIX == *-clang-i686 ]]; then
    apply_patch_with_msg \
      0011-disable-uac-for-installer.patch
  fi
}

build() {
  [[ -d "${srcdir}/${MSYSTEM}" ]] && rm -rf "${srcdir}/${MSYSTEM}"
  mkdir -p "${srcdir}/${MSYSTEM}" && cd "${srcdir}/${MSYSTEM}"

  # The ultimate hack to let the bootstrap compiler use libgcc* libs
  if [[ $MINGW_PACKAGE_PREFIX == *-clang-i686 || $MINGW_PACKAGE_PREFIX == *-clang-x86_64 ]]; then
    export GCC_LIBS_HACK="$(cygpath -am build/missing-libs-hack)"
    mkdir -p "${GCC_LIBS_HACK}"
    cp "$(cygpath -u $(clang -print-libgcc-file-name))" "${GCC_LIBS_HACK}/libgcc.a"
    cp "${MINGW_PREFIX}/lib/libunwind.a" "${GCC_LIBS_HACK}/libgcc_eh.a"
    cp "${MINGW_PREFIX}/lib/libunwind.dll.a" "${GCC_LIBS_HACK}/libgcc_s.a"
    export RUSTFLAGS_BOOTSTRAP="-C link-arg=-L$(cygpath -am build/missing-libs-hack)"
  fi

  # hack to inject the bootstrap compiler
  if [[ $_bootstrapping != "no" && $MINGW_PACKAGE_PREFIX == *-clang-aarch64 ]]; then
    mkdir -p "build/cache/${_stage0date}/"
    cp -f "${srcdir}/cargo-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz" \
      "${srcdir}/rust-std-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz" \
      "${srcdir}/rustc-${_stage0version}-dev-aarch64-pc-windows-gnullvm.tar.xz" \
      "build/cache/${_stage0date}/"
  fi

  if [[ $MINGW_PACKAGE_PREFIX == *-clang-aarch64 ]]; then
    # We have to do the following because rust doesn't count x86_64-w64-mingw32 as a target triple
    OSTYPE="$CARCH-pc-windows-gnullvm"

    # Otherwise it uses gcc during bootstrap, even when we build for clang
    export CARGO_TARGET_${CARCH^^}_PC_WINDOWS_GNULLVM_LINKER="${CC}"

  else
    # We have to do the following because rust doesn't count x86_64-w64-mingw32 as a target triple
    OSTYPE="$CARCH-pc-windows-gnu"

    # Otherwise it uses gcc during bootstrap, even when we build for clang
    export CARGO_TARGET_${CARCH^^}_PC_WINDOWS_GNU_LINKER="${CC}"
  fi

  local -a _rust_conf=()
  if [ "${_bootstrapping}" = "no" ]; then
    _rust_conf+=("--local-rust-root=$(cygpath -m ${MINGW_PREFIX})")
  fi
  if [[ $MINGW_PACKAGE_PREFIX != *-clang-i686 ]]; then
    _rust_conf+=("--enable-vendor")
  fi

  # The rust build uses git if it's available but can't handle cygwin git paths
  # so we try to make git not detect any repo with this
  export GIT_DIR=/dev/null

  # For a faster build:
  # - add --disable-docs and --disable-compiler-docs
  # - compile only rustc by removing --enable-extended
  # - run makepkg-mingw with --nocheck
  # - remove --stage 2

  export RUST_BACKTRACE=1

  MSYS2_ARG_CONV_EXCL="--prefix;--sysconfdir;--localstatedir" \
  ../${_realname}c-${pkgver}-src/configure \
    --prefix=${MINGW_PREFIX} \
    --sysconfdir=${MINGW_PREFIX}/etc \
    --localstatedir=${MINGW_PREFIX}/var/lib \
    --build=$OSTYPE \
    --host=$OSTYPE \
    --target=$OSTYPE \
    --release-channel=stable \
    --release-description="Rev${pkgrel}, Built by MSYS2 project" \
    --enable-ninja \
    --enable-extended \
    --disable-llvm-static-stdcpp \
    --disable-codegen-tests \
    --llvm-root=${MINGW_PREFIX} \
    --python=${MINGW_PREFIX}/bin/python \
    "${_rust_conf[@]}"

  if [[ $MINGW_PACKAGE_PREFIX != *-clang-i686 ]]; then
    # Building out of tree is not officially supported so we have to workaround some things like vendored deps
    cp -r ../${_realname}c-${pkgver}-src/.cargo .
    sed -i "s|directory = \"vendor\"|directory = \"../${_realname}c-${pkgver}-src/vendor\"|" .cargo/config.toml
  fi

  # create the install at a temporary directory
  DEP_NGHTTP_ROOT=${MINGW_PREFIX} \
  DEP_OPENSSL_ROOT=${MINGW_PREFIX} \
  DEP_Z_ROOT=${MINGW_PREFIX} \
  DESTDIR="$PWD"/dest-rust ${MINGW_PREFIX}/bin/python ../${_realname}c-${pkgver}-src/x.py install --stage 2

  # move docs out of the way for splitting
  mv dest-rust/${MINGW_PREFIX}/share/doc dest-doc

  rm -f dest-rust/${MINGW_PREFIX}/bin/libgcc*.dll
  rm -f dest-rust/${MINGW_PREFIX}/bin/libstd*.dll
  rm -f dest-rust/${MINGW_PREFIX}/bin/libwinpthread*.dll
  rm -f dest-rust/${MINGW_PREFIX}/lib/rustlib/$OSTYPE/lib/self-contained/*
}

check() {
  cd "${srcdir}/${MSYSTEM}"
  DEP_NGHTTP_ROOT=${MINGW_PREFIX} \
  DEP_OPENSSL_ROOT=${MINGW_PREFIX} \
  DEP_Z_ROOT=${MINGW_PREFIX} \
  ${MINGW_PREFIX}/bin/python ../${_realname}c-${pkgver}-src/x.py test --stage 2 --exclude src/test/debuginfo
}


package_rust() {
  depends=("${MINGW_PACKAGE_PREFIX}-cc"
           "${MINGW_PACKAGE_PREFIX}-curl"
           "${MINGW_PACKAGE_PREFIX}-libxml2"
           "${MINGW_PACKAGE_PREFIX}-libssh2")

  cd "${srcdir}/${MSYSTEM}"

  cp -a dest-rust/* "$pkgdir"
  install -Dm644 ${srcdir}/${_realname}c-${pkgver}-src/LICENSE-APACHE "${pkgdir}${MINGW_PREFIX}/share/licenses/${_realname}/LICENSE-APACHE"
  install -Dm644 ${srcdir}/${_realname}c-${pkgver}-src/LICENSE-MIT "${pkgdir}${MINGW_PREFIX}/share/licenses/${_realname}/LICENSE-MIT"

  # delete unnecessary files, e.g. components and manifest files only used for the uninstall script
  cd "$pkgdir"/${MINGW_PREFIX}/lib/rustlib
  rm components install.log manifest-* rust-installer-version uninstall.sh

  install -d "$pkgdir/${MINGW_PREFIX}/share/bash-completion/completions"
  mv "${pkgdir}${MINGW_PREFIX}/etc/bash_completion.d/cargo" \
     "${pkgdir}${MINGW_PREFIX}/share/bash-completion/completions/cargo"

}

package_rust-docs() {
  pkgdesc='Documentation for the Rust programming language'
  conflicts=("${MINGW_PACKAGE_PREFIX}-${_realname}<1.52.0")

  cd "${srcdir}/${MSYSTEM}"
  install -Dm644 ${srcdir}/${_realname}c-${pkgver}-src/LICENSE-APACHE "${pkgdir}${MINGW_PREFIX}/share/licenses/$pkgname/LICENSE-APACHE"
  install -Dm644 ${srcdir}/${_realname}c-${pkgver}-src/LICENSE-MIT "${pkgdir}${MINGW_PREFIX}/share/licenses/$pkgname/LICENSE-MIT"

  install -d "$pkgdir"/${MINGW_PREFIX}/share/
  cp -a dest-doc "$pkgdir"/${MINGW_PREFIX}/share/doc
}

# template start; name=mingw-w64-splitpkg-wrappers; version=1.0;
# vim: set ft=bash :

# generate wrappers
for _name in "${pkgname[@]}"; do
  _short="package_${_name#${MINGW_PACKAGE_PREFIX}-}"
  _func="$(declare -f "${_short}")"
  eval "${_func/#${_short}/package_${_name}}"
done
# template end;
